package main

import (
	"common"
	"common/ipv6"
	"context"
	"errors"
	"fmt"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"

	"time"
	"uploadmp4/db"
	"uploadmp4/upload"
	watcherWrap "uploadmp4/watcher"
)

var rootDir = "/data_dir/video/record/live"
var p2puid = ""

func StartDb() {
	_, err := db.Opendb("files.db")
	if err != nil {
		panic(fmt.Sprintf("open db err: %s", err))
	}
	fmt.Println("open db ok")
}

func ParseUploadKey(file string) (string, bool) {
	if strings.HasPrefix(file, rootDir) {
		tmp := file[len(rootDir):]
		if tmp[0] == '/' {
			tmp = tmp[1:]
		}
		parts := strings.Split(tmp, "/")
		if len(parts) == 2 {
			ipsId := parts[0]
			name := parts[1]
			if len(name) > 8 {
				dayString := name[0:8]
				key := strings.Join([]string{ipsId, dayString, name}, "/")
				return key, true
			}
		}
	}
	return "", false
}

func UploadFile(ctx context.Context) {
	go func() {
		for {
			t1 := time.Now()
			file := db.GetUnUpload(ctx)
			if len(file) == 0 {
				time.Sleep(time.Second)
				continue
			}
			fmt.Println("get file ", file)

			if key, ok := ParseUploadKey(file); ok {
				fs, err := os.Stat(file)
				if err != nil {
					if errors.Is(err, os.ErrNotExist) {
						fmt.Println("not exist")
						db.SetFileFlag(ctx, file)
					}
					continue
				}
				t2 := time.Now()
				fp, err := os.Open(file)
				if err != nil {
					fmt.Println("Open file ", file, err)
					continue
				}
				if upload.UploadFile(key, fp, fs.Size()) != 0 {
					fmt.Println("upload failed, continue")
					time.Sleep(time.Second * 3)
					fp.Close()
					continue
				}
				fp.Close()
				t3 := time.Now()
				fmt.Println("### use time", t2.Sub(t1), t3.Sub(t2))
			}
			db.SetFileFlag(ctx, file)
		}
	}()
}

func main() {
	ctx := context.Background()
	StartDb()

	ids := GetIPCIds(rootDir)
	fmt.Println(ids)
	p2puid, _ = common.GetP2pUid()
	if len(p2puid) == 0 {
		p2puid = ipv6.GetIPV4()
	}
	if globalConfig.scanMp4BeforeNow {
		for _, id := range ids {
			subdir := path.Join(rootDir, id)
			ScanOldMP4File(ctx, subdir)
		}
	}
	apikey := "15gDMT9uMinAFi5x1sVpWaftLV8UYJp8t8cLG1r8HHQUbMiJBjxNsZnMfzWvErLAQ6ym53K4C6A22iKUm"

	if upload.Init(apikey) != 0 {
		fmt.Println("init sdk error")
		return
	}
	if globalConfig.uploadFile {
		UploadFile(ctx)
	}
	go StartDelTimer(ctx)
	watcherWrap.NewWatcher()
	watcherWrap.Run(ctx)
	ScanIPC(rootDir)

	scan := time.NewTicker(time.Second * 60)
	report := time.NewTicker(time.Second * 60)
	for {
		select {
		case <-scan.C:
			ScanIPC(rootDir)
		case <-report.C:
			Report()
		case <-ctx.Done():
			break
		}
	}

}

func ScanIPC(rootDir string) {
	ids := GetIPCIds(rootDir)
	for _, id := range ids {
		subdir := path.Join(rootDir, id)
		if !watcherWrap.IsDirWatching(subdir) {
			fmt.Println("add watch ", subdir)
			watcherWrap.Add(subdir)
		} else {
			//fmt.Println("dir is in watching", subdir)
		}
	}
	UpdateIPC(strings.Join(ids, " "))
}

func GetIPCIds(folder string) []string {
	resutl := make([]string, 0)
	entrys, err := os.ReadDir(folder)
	if err != nil {
		fmt.Println(err)
		return resutl
	}
	for _, entry := range entrys {
		resutl = append(resutl, entry.Name())
	}
	return resutl
}
func UpdateIPC(ipc string) error {
	url := "http://estore.guanjieai.com:8091/updateIPC"
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil
	}
	client := &http.Client{
		Timeout: 6 * time.Second,
	}
	q := req.URL.Query()
	q.Add("ipc", ipc)
	req.URL.RawQuery = q.Encode()
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()

	return err
}
func Report() error {
	url := "http://estore.guanjieai.com:8091/update"
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil
	}
	all, remain := db.GetRemainCount(context.Background())
	client := &http.Client{
		Timeout: 6 * time.Second,
	}

	q := req.URL.Query()
	q.Add("id", p2puid)
	q.Add("all", strconv.Itoa(int(all)))
	q.Add("remain", strconv.Itoa(int(remain)))
	req.URL.RawQuery = q.Encode()
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()

	return err
}
